package br.com.felix.fwt.log;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Semaphore;
import org.apache.log4j.Logger;



public class FelixLogger4J extends Logger {

	private static Queue<Log> logQueue = new ConcurrentLinkedQueue<Log>();
	
	private static File logFile;
	
	private static Semaphore semaphore = new Semaphore(1);
	
	private String className;
	
	private static Map<String,FelixLogger4J> mapLoggers = new HashMap<String,FelixLogger4J>();
	
	//TODO: fix
	private static String logFilePath;
	
	static{
		logFile = new File(logFilePath);
	}
	
	public static FelixLogger4J getLogger(Class clazz){
		FelixLogger4J logger = mapLoggers.get(clazz);
		if(logger == null){
			logger = new FelixLogger4J(FelixLogger4J.class.getName());
			logger.className = clazz.getCanonicalName();
			mapLoggers.put(clazz.getCanonicalName(), logger);
		}
		return logger;
	}
	
	
	@Override
	public void debug(Object arg0, Throwable arg1) {
		logQueue.add(new Log(arg1,arg0.toString(),Thread.currentThread().getId(),"DEBUG"));
		dump();
	}


	@Override
	public void debug(Object arg0) {
		logQueue.add(new Log(null,arg0.toString(),Thread.currentThread().getId(),"DEBUG"));
		dump();
	}


	protected FelixLogger4J(String arg0) {
		super(arg0);
	}

	@Override
	public void error(Object arg0, Throwable arg1) {
		logQueue.add(new Log(arg1,arg0.toString(),Thread.currentThread().getId(),"ERROR"));
		dump();
	}

	@Override
	public void error(Object arg0) {
		logQueue.add(new Log(null,arg0.toString(),Thread.currentThread().getId(),"ERROR"));
		dump();
	}

	@Override
	public void fatal(Object arg0, Throwable arg1) {
		logQueue.add(new Log(arg1,arg0.toString(),Thread.currentThread().getId(),"FATAL"));
		dump();
	}

	@Override
	public void fatal(Object arg0) {
		logQueue.add(new Log(null,arg0.toString(),Thread.currentThread().getId(),"FATAL"));
		dump();
	}

	@Override
	public void info(Object arg0, Throwable arg1) {
		logQueue.add(new Log(arg1,arg0.toString(),Thread.currentThread().getId(),"INFO"));
		dump();
	}

	@Override
	public void info(Object arg0) {
		logQueue.add(new Log(null,arg0.toString(),Thread.currentThread().getId(),"INFO"));
		dump();
	}

	@Override
	public void warn(Object arg0, Throwable arg1) {
		logQueue.add(new Log(arg1,arg0.toString(),Thread.currentThread().getId(),"WARN"));
		dump();
	}

	@Override
	public void warn(Object arg0) {
		logQueue.add(new Log(null,arg0.toString(),Thread.currentThread().getId(),"WARN"));
		dump();
	}
	
	private synchronized void dump(){
		try {
			semaphore.acquire();
			if(!logFile.exists()){
				try {
					logFile.createNewFile();
				}
				catch (IOException e) {
					e.printStackTrace();
					return;
				}
			}
			FileWriter fw = new FileWriter(logFile,true);
			BufferedWriter bw = new BufferedWriter(fw);
			PrintWriter pw = new PrintWriter(bw);
			Log log;
			while(!logQueue.isEmpty()){
				log = logQueue.poll();
				pw.printf("%1$td-%1$tm-%1$tY %1$tT %2$10d [%3$-5s] <%4$-70s>  %5$s%n", new Date(), log.threadId, log.severity, className ,log.message);
				if(log.exception!=null){
					log.exception.printStackTrace(pw);
				}
			}
			pw.flush();
			pw.close();
			semaphore.release();
		}
		catch (InterruptedException e) {
			e.printStackTrace();
			return;
		}
		catch (IOException e) {
			e.printStackTrace();
			return;
		}
	}
}
